﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Pipes.Queries.Execution;

namespace Pipes.Queries.Model.Query
{
  public class Conditional : IExpression
  {
    private List<ConditionBranch> _branches = new List<ConditionBranch>();

    public IList<ConditionBranch> Branches
    {
      get
      {
        return _branches;
      }
    }
    public bool Deterministic { get { return true; } }
    public Pipes.Queries.MetaData.GeneralDataType InferredType { get; set; }
    public IExpression Else { get; set; }
    public IExpression Root { get; set; }

    public override string ToString()
    {
      var builder = new StringBuilder("CASE ");
      if (this.Root != null)
      {
        builder.Append(this.Root.ToString());
        builder.Append(" ");
      }
      foreach (var branch in _branches) builder.Append(branch.ToString());
      if (this.Else != null)
      {
        builder.Append(" ELSE ");
        builder.Append(this.Else.ToString());
      }
      builder.Append(" END");
      return builder.ToString();
    }

    public void Visit(Parser.IQueryVisitor visitor)
    {
      visitor.Visit(this);
    }
    
    public object Evaluate()
    {
      if (this.Root == null)
      {
        foreach (var branch in this.Branches)
        {
          if (ExecUtils.IsTrue(branch.Condition.Evaluate()))
          {
            return branch.Branch.Evaluate();
          }
        }
      }
      else
      {
        var root = this.Root.Evaluate();
        foreach (var branch in this.Branches)
        {
          if (ExecUtils.IsTrue(OperatorExecution.Equals(root, branch.Condition.Evaluate())))
          {
            return branch.Branch.Evaluate();
          }
        }
      }

      if (this.Else == null)
      {
        return DBNull.Value;
      }
      else
      {
        return this.Else.Evaluate();
      }
    }
  }
}
